package com.mall.shopping.services;

import com.alibaba.fastjson.JSON;
import com.mall.shopping.ICartService;
import com.mall.shopping.constant.GlobalConstants;
import com.mall.shopping.constants.ShoppingRetCode;
import com.mall.shopping.converter.CartItemConverter;
import com.mall.shopping.dal.entitys.Item;
import com.mall.shopping.dal.persistence.ItemMapper;
import com.mall.shopping.dto.*;
import com.mall.shopping.utils.ExceptionProcessorUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Service;
import org.redisson.api.RList;
import org.redisson.api.RMap;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Collection;
import java.util.List;

import java.util.Collection;

import java.util.ArrayList;
@Slf4j
@Service
public class ICartServiceImpl implements ICartService {
    @Autowired  //用于获得mysql中商品信息
    ItemMapper itemMapper;

    @Autowired  //用于操作redis数据库
    private RedissonClient redissonClient;

    @Override
    public CartListByIdResponse getCartListById(CartListByIdRequest request) {
        request.requestCheck();

        CartListByIdResponse cartListByIdResponse = new CartListByIdResponse();
        cartListByIdResponse.setCode(ShoppingRetCode.SUCCESS.getCode());
        cartListByIdResponse.setMsg(ShoppingRetCode.SUCCESS.getMessage());

        try {
            RMap<Object, Object> productMap = redissonClient.getMap(String.valueOf(request.getUserId()));
            ArrayList<CartProductDto> cartProductDtos = new ArrayList<>();
            Collection<Object> values = productMap.values();


            for (Object value : values) {
                CartProductDto cart = (CartProductDto) value;
                cartProductDtos.add(cart);
            }
//            productMap.values().forEach(obj -> {
//                CartProductDto cartProductDto = JSON.parseObject(obj.toString(), CartProductDto.class);
//                cartProductDtos.add(cartProductDto);
//            });
            cartListByIdResponse.setCode(ShoppingRetCode.SUCCESS.getCode());
            cartListByIdResponse.setMsg(ShoppingRetCode.SUCCESS.getMessage());
            cartListByIdResponse.setCartProductDtos(cartProductDtos);
        } catch (Exception e) {
            log.error("CartServiceImpl.getCartListById Occur Exception :" + e);
            ExceptionProcessorUtils.wrapperHandlerException(cartListByIdResponse, e);
        }

        return cartListByIdResponse;
    }
    private String generatorCartItemKey(long userId) {
        StringBuilder sb = new StringBuilder(GlobalConstants.CART_ITEM_CACHE_PREFIX);
        sb.append(":").append(userId);
        return sb.toString();
    }

    @Override
    public AddCartResponse addToCart(AddCartRequest request) {
        //这里要求将数据写到redis中 使用Map进行储存 map可以储存多个value域 理论上可以实现

        //返回对象
        AddCartResponse addCartResponse = new AddCartResponse();

        try{
            //有效参数校验
            request.requestCheck();

            //通过RedissonClient操纵redis数据库
            RMap<Object, Object> map = redissonClient.getMap(String.valueOf(request.getUserId()));

            //通过productId判断redis中是否已经储存了该数据
            CartProductDto cart = (CartProductDto) map.get(request.getItemId());
            if (cart != null) { // 是则改变数量 这里对数量进行一个限制
                Long productNum = cart.getProductNum();
                productNum += request.getNum();
                if(productNum > cart.getLimitNum()){
                    productNum = cart.getLimitNum();
                }
                cart.setProductNum(productNum);

                //将数据放入redis中
                map.put(request.getItemId(),cart);
            } else {    //否则添加
                //通过productId来查询tb_item表来获得商品信息  可以借助CartProductDto
                Item item = itemMapper.selectByPrimaryKey(request.getItemId());

                //redis储存对象
                CartProductDto cartProductDto = new CartProductDto();
                cartProductDto = CartItemConverter.item2Dto(item);  //这里可能会报异常 静态方法的引用
                cartProductDto.setChecked("true");

                //TODO 以下是否可以更新为三目表达式
                cartProductDto.setProductNum(request.getNum() > item.getLimitNum()?(long)item.getLimitNum():request.getNum());

//                if(cartProductDto.getProductNum() > cartProductDto.getLimitNum()){
//                    cartProductDto.setProductNum(cartProductDto.getLimitNum());
//                }

                cartProductDto.setProductNum((long)request.getNum());

                //将数据放入redis中
                map.put(request.getItemId(),cartProductDto);
            }

            //对返回结果进行封装
            addCartResponse.setCode(ShoppingRetCode.SUCCESS.getCode());
            addCartResponse.setMsg(ShoppingRetCode.SUCCESS.getMessage());

        }catch(Exception e){
            //捕捉到任何异常 作出回应
            addCartResponse.setCode(ShoppingRetCode.SYSTEM_ERROR.getCode());
            addCartResponse.setCode(ShoppingRetCode.SYSTEM_ERROR.getMessage());
        }

        return addCartResponse;
    }

    @Override
    public UpdateCartNumResponse updateCartNum(UpdateCartNumRequest request) {
        //这里主要是更新产品数量以及选中信息

        //返回对象
        UpdateCartNumResponse updateCartNumResponse = new UpdateCartNumResponse();

        try{
            //参数校验
            request.requestCheck();

            //通过RedissonClient操纵redis数据库
            RMap<Object, Object> map = redissonClient.getMap(String.valueOf(request.getUserId()));

            //根据productId获得对应数据
            CartProductDto cart = (CartProductDto) map.get(request.getItemId());
            //todo 更新数量和选中状态 这里是否会报类型转化错误
            cart.setProductNum(request.getNum()>cart.getLimitNum()?cart.getLimitNum():request.getNum());
            cart.setChecked(request.getChecked());

            //将更新后的数据放入数据库中 默认会覆盖原来的数据
            map.put(request.getItemId(),cart);

            //设置成功状态码
            updateCartNumResponse.setCode(ShoppingRetCode.SUCCESS.getCode());
            updateCartNumResponse.setMsg(ShoppingRetCode.SUCCESS.getMessage());

        }catch(Exception e){
            //捕捉到任何异常 作出回应
            updateCartNumResponse.setCode(ShoppingRetCode.SYSTEM_ERROR.getCode());
            updateCartNumResponse.setCode(ShoppingRetCode.SYSTEM_ERROR.getMessage());
        }
        return updateCartNumResponse;
    }

    @Override
    public CheckAllItemResponse checkAllCartItem(CheckAllItemRequest request) {
        //新建返回对象
        CheckAllItemResponse checkAllItemResponse = new CheckAllItemResponse();

        try{
            //参数校验
            request.requestCheck();

            RMap<Object, Object> map = redissonClient.getMap(String.valueOf(request.getUserId()));
            Collection<Object> values = map.values();


            for (Object value : values) {
                CartProductDto cart = (CartProductDto) value;
                cart.setChecked(request.getChecked());
                map.put(cart.getProductId(),cart);
            }

            checkAllItemResponse.setCode(ShoppingRetCode.SUCCESS.getCode());
            checkAllItemResponse.setMsg(ShoppingRetCode.SUCCESS.getMessage());
        } catch (Exception e){
            checkAllItemResponse.setCode(ShoppingRetCode.SYSTEM_ERROR.getCode());
            checkAllItemResponse.setMsg(ShoppingRetCode.SYSTEM_ERROR.getMessage());
        }

        return checkAllItemResponse;
    }

    @Override
    public DeleteCartItemResponse deleteCartItem(DeleteCartItemRequest request) {
        //这里是根据传入的uid和pid进行商品的删除

        //返回对象
        DeleteCartItemResponse deleteCartItemResponse = new DeleteCartItemResponse();

        try{
            //参数校验
            request.requestCheck();

            //获得redis数据库操作对象
            RMap<Object, Object> map = redissonClient.getMap(String.valueOf(request.getUserId()));
            //执行删除操作
            map.remove(request.getItemId());

            deleteCartItemResponse.setCode(ShoppingRetCode.SUCCESS.getCode());
            deleteCartItemResponse.setMsg(ShoppingRetCode.SUCCESS.getMessage());

        }catch (Exception e){
            deleteCartItemResponse.setCode(ShoppingRetCode.SYSTEM_ERROR.getCode());
            deleteCartItemResponse.setMsg(ShoppingRetCode.SYSTEM_ERROR.getMessage());
        }
        return deleteCartItemResponse;
    }

    @Override
    public DeleteCheckedItemResposne deleteCheckedItem(DeleteCheckedItemRequest request) {

        DeleteCheckedItemResposne deleteCheckedItemResposne = new DeleteCheckedItemResposne();
        try{
            request.requestCheck();
            RMap<Object, Object> map = redissonClient.getMap(String.valueOf(request.getUserId()));
            Collection<Object> values = map.values();
            for (Object value : values) {
                CartProductDto cartProductDto = (CartProductDto) value;
                Long productId = cartProductDto.getProductId();
                if("true".equals(cartProductDto.getChecked())){
                    map.remove(productId);
                }
            }
            deleteCheckedItemResposne.setCode(ShoppingRetCode.SUCCESS.getCode());
            deleteCheckedItemResposne.setMsg(ShoppingRetCode.SUCCESS.getMessage());

        }catch (Exception e){
            deleteCheckedItemResposne.setCode(ShoppingRetCode.SYSTEM_ERROR.getCode());
            deleteCheckedItemResposne.setMsg(ShoppingRetCode.SYSTEM_ERROR.getMessage());
        }
        return deleteCheckedItemResposne;
    }

    @Override
    public ClearCartItemResponse clearCartItemByUserID(ClearCartItemRequest request) {
        ClearCartItemResponse clearCartItemResponse = new ClearCartItemResponse();

        try{

            request.requestCheck();

            //获得当前用户所有订单
            RMap<Object, Object> map = redissonClient.getMap(String.valueOf(request.getUserId()));

            //获得要清楚购物车中的商品的商品id,并删除
            List<Long> productIds = request.getProductIds();
            for (Long productId : productIds) {
            map.remove(productId);
            }
            clearCartItemResponse.setCode(ShoppingRetCode.SUCCESS.getCode());
            clearCartItemResponse.setMsg(ShoppingRetCode.SUCCESS.getMessage());
        }catch (Exception e){
            clearCartItemResponse.setCode(ShoppingRetCode.SYSTEM_ERROR.getCode());
            clearCartItemResponse.setMsg(ShoppingRetCode.SYSTEM_ERROR.getMessage());
        }

        return clearCartItemResponse;

    }
}
